/*
 *  scoreBoard - ScoreBoardApp.cpp
 *  Copyright 2011 W. Reckman. All rights reserved.
 */
#include "Settings.h"
#include "PlayerHead.h"
#include "ScoreBoardApp.h"

const string ScoreBoardApp::CONFIG_FILE = "config.ini";

//--------------------------------------------------------------
ScoreBoardApp::ScoreBoardApp()
: s( Settings::getInstance() ), board( *this ), videoController( *this ),
  imageFileManager( *this ), dataReceiver( *this ), screenModeChanged( 3 ),
  debugDrawingEnabled( false ), showAppFrameRate( false )
{}

//--------------------------------------------------------------
void ScoreBoardApp::setup() {
	ofSetLogLevel( OF_LOG_NOTICE );
	
	s.loadFromFile( CONFIG_FILE );
	
	int maxFPS = ofToInt( *s.getValue( "fps_max", "0" ) );
	ofSetFrameRate( maxFPS );
	ofLog( OF_LOG_NOTICE, "max framerate set to: %i fps", maxFPS );
	
	string fontFile = *s.getValue( "font_file", "monaco.ttf" );
	int fontSize = ofToInt( *s.getValue( "font_size", "24" ) );
	
	board.setup();
	font.loadFont( fontFile, fontSize );
	
	//--window
	bool bWindowFullscreen = parseBool( *s.getValue( "window_fullscreen", "false" ) );
	if ( bWindowFullscreen ) {
		ofSetWindowPosition( ofToInt( *s.getValue( "window_set_position", "0" ) ), 0 );
		ofSetFullscreen( true );
	} else {
		ofSetFullscreen( false );
	}
	
	//--canvas
	canvasWidth = ofToInt( *s.getValueInGroup( "canvas_width", "settings", "-1" ) );
	canvasHeight = ofToInt( *s.getValueInGroup( "canvas_height", "settings", "-1" ) );
	if ( canvasWidth == -1 || canvasHeight == -1 ) {
		ofLog( OF_LOG_FATAL_ERROR, "(ScoreBoardApp.cpp) missing config key canvas_width or canvas_height" );
		//FIXME: FATAL_ERROR
	} else {
		ofLog( OF_LOG_WARNING, "(ScoreBoardApp.cpp) using %ix%i as canvas texture resolution", canvasWidth, canvasHeight );
		
		fboTexture.allocate( canvasWidth, canvasHeight );
	}
	
	ofEnableAlphaBlending();
	videoController.setup();
	dataReceiver.setup();
	
#ifdef IGNORE_EXISTING_PHOTOBOOTH_FILES
	remoteIO.setup( false );
#else
	remoteIO.setup( true );
#endif
	
	ofAddListener( remoteIO.onNewPhotoboothFile, &imageFileManager, &ImageFileManager::onNewPhotoboothFile );	
}

//--------------------------------------------------------------
void ScoreBoardApp::update() {
	appFrameRate = ofGetFrameRate();
	
	board.update();
	videoController.update( board.getBalanceMeter().getBalanceFloat() );
	remoteIO.update();
	dataReceiver.update();
	
	for ( int i = 0; i < board.getPlayerHeads().size(); ++i ) {
		PlayerHead* ph = board.getPlayerHead( i );
		ph->update();
	}
	
	//NOTE: the counter construction is necessary to overcome delayed updating of screen dimensions by oF
	if ( screenModeChanged > 0 ) {
		screenModeChanged--;
		if ( screenModeChanged == 0 ) setViewportSize( ofGetWidth(), ofGetHeight() );
	}
}

//--------------------------------------------------------------
void ScoreBoardApp::draw() {
	static const int topLine = 20, lineHeight = 14;
	
	ofBackground( 0, 0, 0 );
	
	ofEnableAlphaBlending();
	fboTexture.begin();
	
	videoController.draw();
	
	
	/* (debug) DRAW DEBUG */
	if ( debugDrawingEnabled ) {
		const ofRectangle& bb = board.getBoundingBox();
		const BoardModel::vec_int& rl = board.getRowLanes();
		const BoardModel::vec_int& cl = board.getColumnLanes();
		
		ofPushStyle();
		
		ofSetLineWidth( 2.0f );
		
		ofSetColor( 255, 31, 31 );
		for ( int i = 0; i < rl.size(); ++i ) {
			ofLine( bb.x, rl[i], bb.x + bb.width, rl[i] );
		}
		
		for ( int i = 0; i < cl.size(); ++i ) {
			ofSetColor( 255, 31, 31 );
			ofLine( cl[i], bb.y, cl[i], bb.y + bb.height );
		}
		
		ofPopStyle();
	}
	
	
	for ( int i = 0; i < board.getPlayerHeads().size(); ++i ) {
		PlayerHead* ph = board.getPlayerHead( i );
		ph->draw();
	}
	
	ofSetColor( 255, 255, 255 );
	drawTtfStringCentered( font, "WINNERS", canvasWidth / 2, 50 );
	
	fboTexture.end();
	
	
	fboTexture.draw( 0, 0, viewportWidth, viewportHeight );
	
	if ( showAppFrameRate ) {
		char fpsString[100];
		snprintf( fpsString, sizeof( fpsString ), "FPS: %i", appFrameRate );
		ofDrawBitmapString( fpsString, 10, topLine );
	}
	
	if ( debugDrawingEnabled ) {
		char gameNumString[100];
		snprintf( gameNumString, sizeof( gameNumString ), "game#: %i", board.getCurrentGameNum() );
		ofDrawBitmapString( gameNumString, 10, topLine + lineHeight );
		
		char balanceString[100];
		snprintf( balanceString, sizeof( balanceString ), "balance: %1.2f", board.getBalanceMeter().getBalanceFloat() );
		ofDrawBitmapString( balanceString, 10, topLine + lineHeight * 2 );
		
		char queueAndPlayersString[100];
		snprintf( queueAndPlayersString, sizeof( queueAndPlayersString ), "q/p: %lu/%lu", imageFileManager.getQueuedInfoItems().size(), board.getPlayerHeads().size() );
		ofDrawBitmapString( queueAndPlayersString, 10, topLine + lineHeight * 3 );
		
//		char timeString[100];
//		snprintf( timeString, sizeof( timeString ), "time: %.3f", board.getTime() );
//		ofDrawBitmapString( timeString, 10, topLine + lineHeight * 4 );
	}
}


//--------------------------------------------------------------
const BoardModel& ScoreBoardApp::getBoard() const { return board; }
BoardModel& ScoreBoardApp::getBoard() { return board; }
const ImageFileManager& ScoreBoardApp::getImageFileManager() const { return imageFileManager; }
ImageFileManager& ScoreBoardApp::getImageFileManager() { return imageFileManager; }


//--------------------------------------------------------------
//FIXME: is this function called with incorrect parameters? (fullscreen resolution is wrong)
void ScoreBoardApp::setViewportSize( int w, int h ) {
#ifdef FORCE_VIEWPORT_4_TO_3
	float ft = 3.0f / 4.0f, tf = 4.0f / 3.0f;
	if ( w * ft > h ) w = h * tf;
	else if ( h * tf > w ) h = w * ft;
#endif
	
	viewportWidth = w;
	viewportHeight = h;
	
	ofLog( OF_LOG_NOTICE, "(ScoreBoardApp.cpp) viewport resolution set to %i x %i", viewportWidth, viewportHeight );
}

//--------------------------------------------------------------
void ScoreBoardApp::setFullscreen( bool fs ) {
	screenModeChanged = 3;
	ofSetFullscreen( fs );
}

//--------------------------------------------------------------
void ScoreBoardApp::toggleFullscreen() {
	screenModeChanged = 3;
	ofToggleFullscreen();
}

//--------------------------------------------------------------
int ScoreBoardApp::getCanvasWidth() const { return canvasWidth; }
int ScoreBoardApp::getCanvasHeight() const { return canvasHeight; }


//--------------------------------------------------------------
void ScoreBoardApp::keyPressed( int key ) {
	switch ( key ) {
		case 'f': case 'F':
			toggleFullscreen();
			break;
		case 'e': case 'E':
			setFullscreen( true );
			break;
		case '@': case '2':
			debugDrawingEnabled = ! debugDrawingEnabled;
			break;
		case '?':
			showAppFrameRate = ! showAppFrameRate;
			break;
	}
}

//--------------------------------------------------------------
void ScoreBoardApp::keyReleased( int key ) {}
void ScoreBoardApp::mouseMoved( int x, int y ) {}
void ScoreBoardApp::mouseDragged( int x, int y, int button ) {}
void ScoreBoardApp::mousePressed( int x, int y, int button ) {}
void ScoreBoardApp::mouseReleased( int x, int y, int button ) {}
void ScoreBoardApp::windowResized( int w, int h ) {}
